﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Sparklings.Gui
{
    abstract class DraggableAndClickableControl
    {
        protected DraggableAndClickableControl(Rectangle viewBoundingBox, Vector2 dataDimensions = default(Vector2))
        {
            ViewBoundingBox = viewBoundingBox;
            DataDimensions = dataDimensions;

            Dragging = false;
            LastMousePos = new Vector2();
            MouseIsDown = false;
            ViewOffset = new Vector2();
        }
        public virtual void Update(GameTime t)
        {
            MouseState mouseState = Mouse.GetState();
            Vector2 currentMousePos = new Vector2(mouseState.X, mouseState.Y);
            if (ViewBoundingBox.Contains((int)StartClickMousePos.X, (int)StartClickMousePos.Y))
            {
                if (MouseIsDown
                    && Mouse.GetState().LeftButton == ButtonState.Released)
                {
                    try
                    {
                        if ((!Dragging)
                            && Vector2.Distance(currentMousePos, StartClickMousePos) < 10)
                        {
                            // Clicking
                            HandleClick(currentMousePos - new Vector2(ViewBoundingBox.Left, ViewBoundingBox.Top) - ViewOffset);
                        }
                    }
                    finally
                    {
                        Dragging = false;
                        MouseIsDown = false;
                    }
                }
                else if (Mouse.GetState().LeftButton == ButtonState.Pressed)
                {
                    if (!MouseIsDown)
                    {
                        StartClickMousePos = currentMousePos;
                    }
                    MouseIsDown = true;
                    if (Vector2.Distance(currentMousePos, StartClickMousePos) >= 10)
                    {
                        // Dragging.
                        if (!Dragging)
                        {
                            ViewOffset += currentMousePos - StartClickMousePos;
                        }
                        else
                        {
                            ViewOffset += currentMousePos - LastMousePos;
                        }
                        CapViewOffset();
                        Dragging = true;
                    }
                }
            }
            else if(ViewBoundingBox.Contains((int)currentMousePos.X, (int)currentMousePos.Y))
            {
                StartClickMousePos = currentMousePos;
            }
            LastMousePos = currentMousePos;
        }

        private void CapViewOffset()
        {
            if (ViewOffset.X > 0)
            {
                ViewOffset.X = 0;
            }
            if (ViewOffset.Y > 0)
            {
                ViewOffset.Y = 0;
            }
            if (ViewOffset.X < -(DataDimensions.X - ViewBoundingBox.Width))
            {
                ViewOffset.X = (DataDimensions.X < ViewBoundingBox.Width) ? 0 : -(DataDimensions.X - ViewBoundingBox.Width);
            }
            if (ViewOffset.Y < -(DataDimensions.Y - ViewBoundingBox.Height))
            {
                ViewOffset.Y = (DataDimensions.Y < ViewBoundingBox.Height) ? 0 : -(DataDimensions.Y - ViewBoundingBox.Height);
            }
        }
        protected abstract void HandleClick(Vector2 clickPos);

        private Rectangle ViewBoundingBox;
        protected Vector2 DataDimensions { get; set; }
        protected bool Dragging { get; private set; }
        protected Vector2 LastMousePos { get; private set; }
        protected bool MouseIsDown { get; private set; }
        protected Vector2 ViewOffset;
        private Vector2 StartClickMousePos;
    }
}
